using System;
using SharpMud.Server.Systems;
using SharpMud.MudLib.SAMPLE.Net;
using System.ComponentModel;

namespace SharpMud.MudLib.SAMPLE
{
#if !Use_Common_MudLib
    [Browsable(true), DisplayName("SharpMUD SAMPLE MudLib")]
	public class MudLibRoot : SharpMud.Server.App.Application
	{
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType);


        private MudLib.SAMPLE.Commands.CommandManager _CommandManager;
        private MudLib.SAMPLE.Entities.PlayerSystem _PlayerSystem;
        private MudLib.Core.Scripting.ScriptManager _ScriptManager;
        private MudLib.Core.Time.MudTimeSystem _MudTimeSystem;
        private Environment.EnvironmentSystem _EnvironmentSystem;
        private Server.Systems.Net.Telnet.TelnetServer<TelnetPlayerSession> _TelnetServer;

        [Browsable(true)]
        public MudLib.SAMPLE.Commands.CommandManager CommandManager
        {
            get { return _CommandManager; }
            set { _CommandManager = value; }
        }

        [Browsable(true)]
        public MudLib.SAMPLE.Entities.PlayerSystem PlayerSystem
        {
            get { return _PlayerSystem; }
            set { _PlayerSystem = value; }
        }

        [Browsable(true)]
        public MudLib.Core.Scripting.ScriptManager ScriptManager
        {
            get { return _ScriptManager; }
            set { _ScriptManager = value; }
        }

        [Browsable(true)]
        public MudLib.Core.Time.MudTimeSystem MudTimeSystem
        {
            get { return _MudTimeSystem; }
            set { _MudTimeSystem = value; }
        }

        [Browsable(true)]
        public Environment.EnvironmentSystem EnvironmentSystem
        {
            get { return _EnvironmentSystem; }
            set { _EnvironmentSystem = value; }
        }

        [Browsable(true)]
        public Server.Systems.Net.Telnet.TelnetServer<TelnetPlayerSession> TelnetServer
        {
            get { return _TelnetServer; }
            set { _TelnetServer = value; }
        }

		public MudLibRoot()
			:base()
		{
			this.StatusChanged += new SharpMud.Server.App.AppStatusChangeHandler(App_StatusChanged);
		}

		#region ServerApp Tie-Ins
		protected override Guid AppID
		{
			get
			{
				return new Guid("{BFAF32B0-6DBB-4389-959A-6B4770B7BA88}");
			}
		}

		protected override string SecureAppKey
		{
			get
			{
				return base.GenerateSecureAppKey();
			}
		}

		
		protected override void __Pulse()
		{
			base.__Pulse();
			System.GC.Collect();
			//this.TelnetServer.Pulse();
		}

		protected override void __Initialize()
		{
			base.__Initialize();

			this.LoadConfiguration();
			
			this._Configuration.MudTimeConfig.GoGlobal();	
			this.MudTimeSystem = new SharpMud.MudLib.Core.Time.MudTimeSystem(this._Configuration.MudTimeConfig);
			this.MudTimeSystem.GoGlobal();

			this.ScriptManager = new SharpMud.MudLib.Core.Scripting.ScriptManager();
			//this.ScriptManager.Initialize(this);
			
			this.CommandManager = new SharpMud.MudLib.SAMPLE.Commands.CommandManager(this._Configuration.CommandManagerConfig);
			this.CommandManager.Initialize(this);

			this.PlayerSystem = new SharpMud.MudLib.SAMPLE.Entities.PlayerSystem(this);
			//this.PlayerSystem.Initialize(this);

			this.EnvironmentSystem = new SharpMud.MudLib.SAMPLE.Environment.EnvironmentSystem();
			this.EnvironmentSystem.Initialize(this);

			this.TelnetServer = new Server.Systems.Net.Telnet.TelnetServer<TelnetPlayerSession>(/*TelnetServerConfig*/);
			this.TelnetServer.LoadConfiguration(this.Configuration.TelnetServerConfig);
			this.TelnetServer.Initialize(this);
		}

		protected override void __PreStart()
		{		
			this.MudTimeSystem.Enabled = true;
		
			this.CommandManager.Start();

			this.PlayerSystem.Startup();
			
			this.TelnetServer.Start();
		}

		protected override void __PreStop()
		{	
			//Shutdown the telnet server
			this.TelnetServer.Stop();
			this.TelnetServer.Dispose();
			this.TelnetServer = null;
			//Shutdown the time system...well...stopping it
			this.MudTimeSystem.Enabled = false;
			//Stop the environment system
			this.EnvironmentSystem.Stop();
			//Shutdown the Command Manager
			this.CommandManager.Stop();
			//Shutdown the Script Manager
			this.ScriptManager = null;
			//Shutdown the Player Manager
			this.PlayerSystem.Players.CloseAllPlayers(true);
			this.PlayerSystem.Shutdown();
		}
		protected override void __PostStop()
		{
			//It *mght* have already been done by an external call...
			//but it won't hurt to do it again...
			//(Some shutting down subsystems make config changes)
			SaveConfiguration();
		}

		protected override void __PrePause()
		{
			//This pauses the server activity time tracker
			//and it prevents *mud* time from advancing
			this.MudTimeSystem.Enabled = false;

			this.TelnetServer.Pause();
		}
        
		protected override void __PreResume()
		{
			//This resumes the server activity time tracker
			this.MudTimeSystem.Enabled = true;

			this.TelnetServer.Resume();
		}
        protected override void __Dispose()
        {
            this.TelnetServer.Dispose();
            this.CommandManager.Dispose();
            this.EnvironmentSystem.Dispose();
            
            base.__Dispose();
        }
		#endregion

		#region Configuration
		public const string DefaultConfigurationFile = @"SharpMud.MudLib.SAMPLE.config";
		protected ServerConfiguration _Configuration;
        [Browsable(true), DisplayName("Configuration")]
        public ServerConfiguration Configuration
		{
			get
			{
				return _Configuration;
			}
            set
            {
                _Configuration = value;
            }
		}
		public override void LoadConfiguration()
		{
			string cfn = MudLibRoot.GetSubfileIntelligently(
				RootConfigurationFolder,DefaultConfigurationFile);
			System.IO.FileStream fs;
			System.Xml.Serialization.XmlSerializer xs;

			log.Info("Loading MudLib configuration");
			try
			{
				xs = new System.Xml.Serialization.XmlSerializer(
					typeof(ServerConfiguration) );
			}
			catch(System.NotSupportedException e)
			{

                log.Warn("NotSupportedException thrown while creating application configuration serializer", e); 
                log.Warn("Using DEFAULT configuration");
				this.LoadDefaultConfiguration();
				return;
			}
			try
			{
				fs = new System.IO.FileStream(cfn,System.IO.FileMode.Open);
			}
			catch(System.IO.FileNotFoundException e)
			{
                log.Warn("Mudlib configuration file not found", e);
				//(Should enter some sort of "setup" mode here.)
				log.Warn("Using DEFAULT configuration");
				LoadDefaultConfiguration();
				return;
			}
			catch(System.IO.DirectoryNotFoundException e)
			{
                log.Warn("MudLib configuration directory not found",e);
				//(Should enter some sort of "setup" mode here.)
				log.Warn("Using DEFAULT configuration");
				LoadDefaultConfiguration();
				return;
			}
			try
			{
				this._Configuration = (ServerConfiguration)xs.Deserialize(fs);
			}
			catch(System.NotSupportedException e)
			{
                log.Warn("NotSupportedException thrown while deserializing application configuration", e);
				log.Warn("Using default configuration");
				this.LoadDefaultConfiguration();
				return;
			}
			fs.Close();
		}
		public void LoadDefaultConfiguration()
		{
			ServerConfiguration mlc = new ServerConfiguration();
			
			mlc = ServerConfiguration.Default;
			
			this._Configuration = mlc;
		}
		public override void SaveConfiguration()
		{
			System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(
				typeof(ServerConfiguration)
//				,
//				new System.Type[] {typeof(DynamicTyping.TypeLocation),typeof(DynamicTyping.AssembliedTypeLocation) }
				);
			
			
			System.IO.Stream fs = new System.IO.FileStream(
				MudLibRoot.GetSubfileIntelligently(RootConfigurationFolder,DefaultConfigurationFile),
				System.IO.FileMode.Create);

			xs.Serialize(fs,_Configuration);
			fs.Close();
		}
		#endregion
		
		#region Status Change Events
		private void App_StatusChanged(SharpMud.Server.App.Application sender, SharpMud.Server.App.AppStatusChangeEventArgs e)
		{

		}
		#endregion

		#region File System Tie-Ins
		public string RootEnvironmentFolder
		{
			get
			{
				return MudLibRoot.GetSubfolderIntelligently(this.RootDataFolder,"environment");
			}
		}
		public string RootScriptsFolder
		{
			get
			{
				return MudLibRoot.GetSubfolderIntelligently(this.RootDataFolder,"scripts");
			}
		}
		public string RootEntitiesFolder
		{
			get
			{
				return MudLibRoot.GetSubfolderIntelligently(this.RootDataFolder,"entities");
			}
		}
		#endregion

		public SharpMud.Server.App.IAppExecutionHandle GetAppExecHandle()
		{
			return base._GetAppExecHandle();
		}
	}
#endif
}
